package com.zhengdongzulin.zuke.base

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.lxj.androidktx.core.toast
import com.lxj.androidktx.livedata.StateLiveData
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import com.zhengdongzulin.zuke.R
import com.zhengdongzulin.zuke.app.data.GlobalInfo
import com.zhengdongzulin.zuke.app.login.LoginActivity
import com.zhengdongzulin.zuke.ext.start

/**
 * jeff
 * 2021-03-24 19:50:50
 */
abstract class BaseFragment<VM : ViewModel, VB : ViewDataBinding> : Fragment() {
    protected lateinit var mShareViewModel: GlobalInfo
    private lateinit var mActivity: AppCompatActivity
    protected lateinit var mViewModel: VM
    protected lateinit var mView: VB


    override fun onAttach(context: Context) {
        super.onAttach(context)
        mActivity = context as AppCompatActivity
        mShareViewModel = getAppViewModelProvider().get(GlobalInfo::class.java)
    }

    protected open fun getAppViewModelProvider(): ViewModelProvider {
        return MyApp().getAppViewModelProvider(mActivity)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        if (!MyApp.mFragments.contains(this))
            MyApp.mFragments.add(this)

        isViewCreated = true
        tryLoadData()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mView = DataBindingUtil.inflate(inflater, getLayoutResId(), null, false)
        return mView?.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        mViewModel = initVM()
        (mViewModel as BaseViewModel).apply {
            this.mShareViewModel = this@BaseFragment.mShareViewModel
        }
        initView()
        initData()
        initListener()
        startObserve()
        super.onViewCreated(view, savedInstanceState)
    }

    fun checkLogin(): Boolean {
        if (mShareViewModel.token.value.isNullOrEmpty()) {
            toast("请先登录")
            Intent().start(requireActivity(), LoginActivity::class.java)
            return false
        }
        return true
    }

    fun <T> getObserver(liveData: StateLiveData<T>): Observer<StateLiveData.State> {
        return Observer {
            when (liveData.state.value) {
                StateLiveData.State.Error, StateLiveData.State.Empty -> toast(liveData.errMsg)
            }
        }
    }

    fun <T> getObserver(
        liveData: StateLiveData<T>,
        refreshlayout: SmartRefreshLayout
    ): Observer<StateLiveData.State> {
        refreshlayout.finishRefresh()
        refreshlayout.finishLoadMore()
        return Observer {
            when (liveData.state.value) {
                StateLiveData.State.Error, StateLiveData.State.Empty -> toast(liveData.errMsg)
            }
        }
    }

    fun <T> observer(liveData: StateLiveData<T>) {
        when (liveData.state.value) {
            StateLiveData.State.Error, StateLiveData.State.Empty -> toast(liveData.errMsg)
        }
    }

    fun getObserver(errStr: String): Observer<StateLiveData.State> {
        return Observer {
            when (it) {
                StateLiveData.State.Error, StateLiveData.State.Empty -> toast(errStr)
            }
        }
    }

    abstract fun getLayoutResId(): Int
    abstract fun initVM(): VM
    abstract fun initView()
    abstract fun initData()
    abstract fun initListener()
    abstract fun startObserve()

    private var isViewCreated // 界面是否已创建完成
            = false
    public var misVisibleToUser // 是否对用户可见
            = false
    private var isDataLoaded // 数据是否已请求, isNeedReload()返回false的时起作用
            = false

    /**
     * 视图是否已经对用户可见，系统的方法
     */
    override fun onHiddenChanged(isVisibleToUser: Boolean) {
        misVisibleToUser = isVisibleToUser
        tryLoadData()
    }

    open fun tryLoadData() {
        if (isViewCreated && misVisibleToUser && isParentVisible() && !isDataLoaded) {
            lazyLoad()
            isDataLoaded = true
            // 通知 子 Fragment 请求数据
            dispatchParentVisibleState()
        }
    }

    /**
     * ViewPager场景下，判断父fragment是否可见
     *
     * @return
     */
    private fun isParentVisible(): Boolean {
        val fragment = parentFragment
        return fragment == null || fragment is BaseFragment<*, *> && fragment.misVisibleToUser
    }

    /**
     * ViewPager场景下，当前fragment可见，如果其子fragment也可见，则尝试让子fragment请求数据
     */
    private fun dispatchParentVisibleState() {
        val fragmentManager: FragmentManager = childFragmentManager
        val fragments: List<BaseFragment<*, *>> =
            fragmentManager.getFragments() as List<BaseFragment<*, *>>
        if (fragments.isEmpty()) {
            return
        }
        for (child in fragments) {
            if ((child as BaseFragment).misVisibleToUser) {
                (child as BaseFragment).tryLoadData()
            }
        }
    }

    /**
     * 当视图初始化并且对用户可见的时候去真正的加载数据
     * onCreateView的时候执行的
     */
    protected open fun lazyLoad() {}


    fun setTitle(title: String) {
        var title_content = requireActivity()!!.findViewById<TextView>(R.id.title_content)
        title_content?.let {
            it.text = title
        }
    }

    override fun onDestroy() {
        if (MyApp.mFragments.contains(this))
            MyApp.mFragments.remove(this)
        super.onDestroy()
    }
}